using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace App
{
    internal class DrawHelper
    {

        #region HSL2RGB
        internal static Color HSL2RGB(double hue, double saturation, double luminance)
        {
            double r = 0.0, g = 0.0, b = 0.0;

            if (luminance == 0.0)
                r = g = b = 0.0;
            else if (saturation == 0.0)
                r = g = b = luminance;
            else
            {
                double aux2 = ((luminance <= 0.5) ? luminance * (1.0 + saturation) : luminance + saturation - (luminance * saturation));
                double aux1 = 2.0 * luminance - aux2;

                double[] t3 = new double[] { hue + 1.0 / 3.0, hue, hue - 1.0 / 3.0 };
                double[] clr = new double[] { 0.0, 0.0, 0.0 };

                for (int i = 0; i < 3; i++)
                {
                    if (t3[i] < 0)
                        t3[i] += 1.0;
                    if (t3[i] > 1)
                        t3[i] -= 1.0;

                    if (6.0 * t3[i] < 1.0)
                        clr[i] = aux1 + (aux2 - aux1) * t3[i] * 6.0;
                    else if (2.0 * t3[i] < 1.0)
                        clr[i] = aux2;
                    else if (3.0 * t3[i] < 2.0)
                        clr[i] = (aux1 + (aux2 - aux1) * ((2.0 / 3.0) - t3[i]) * 6.0);
                    else
                        clr[i] = aux1;
                }

                r = clr[0];
                g = clr[1];
                b = clr[2];
            }

            if (r > 1.0)
                r = 1.0;
            if (g > 1.0)
                g = 1.0;
            if (b > 1.0)
                b = 1.0;

            return Color.FromArgb((int)(255.0 * r), (int)(255.0 * g), (int)(255.0 * b));
        } 
        #endregion

        #region GetColor
        internal static Color GetColor(double luminance, Color clr)
        {
            Color col = HSL2RGB(clr.GetHue() / 360.0, clr.GetSaturation() / 2.0, clr.GetBrightness() * 1.025);

            double r = (double)col.R * luminance;
            double g = (double)col.G * luminance;
            double b = (double)col.B * luminance;

            if (r > 255.0)
                r = 255.0;
            if (g > 255.0)
                g = 255.0;
            if (b > 255.0)
                b = 255.0;

            return Color.FromArgb((int)r, (int)g, (int)b);
        } 
        #endregion

        #region DrawRoundRectangle
        internal static void DrawRoundRectangle(Graphics g, Pen pen, Rectangle rectangle, float radius)
        {
            float size = radius * 2f;

            GraphicsPath gp = new GraphicsPath();
            gp.AddArc(rectangle.X, rectangle.Y, size, size, 180, 90);
            gp.AddArc(rectangle.X + rectangle.Width - size, rectangle.Y, size, size, 270, 90);
            gp.AddArc(rectangle.X + rectangle.Width - size, rectangle.Y + rectangle.Height - size, size, size, 0, 90);
            gp.AddArc(rectangle.X, rectangle.Y + rectangle.Height - size, size, size, 90, 90);
            gp.CloseFigure();
            g.DrawPath(pen, gp);
            gp.Dispose();
        } 
        #endregion

        #region FillRoundRectangle
        internal static void FillRoundRectangle(Graphics g, Brush brush, Rectangle rectangle, float radius)
        {
            float size = radius * 2f;

            GraphicsPath gp = new GraphicsPath();
            gp.AddArc(rectangle.X, rectangle.Y, size, size, 180, 90);
            gp.AddArc(rectangle.X + rectangle.Width - size, rectangle.Y, size, size, 270, 90);
            gp.AddArc(rectangle.X + rectangle.Width - size, rectangle.Y + rectangle.Height - size, size, size, 0, 90);
            gp.AddArc(rectangle.X, rectangle.Y + rectangle.Height - size, size, size, 90, 90);
            gp.CloseFigure();
            g.FillPath(brush, gp);
            gp.Dispose();
        } 
        #endregion

        #region DrawTopRoundRectangle
        internal static void DrawTopRoundRectangle(Graphics g, Pen pen, Rectangle rectangle, float radius)
        {
            float size = radius * 2f;

            GraphicsPath gp = new GraphicsPath();
            gp.AddArc(rectangle.X, rectangle.Y, size, size, 180, 90);
            gp.AddArc(rectangle.X + rectangle.Width - size, rectangle.Y, size, size, 270, 90);
            gp.AddLine(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height, rectangle.X, rectangle.Y + rectangle.Height);
            gp.CloseFigure();
            g.DrawPath(pen, gp);
            gp.Dispose();
        } 
        #endregion

        #region FillTopRoundRectangle
        internal static void FillTopRoundRectangle(Graphics g, Brush brush, Rectangle rectangle, float radius)
        {
            float size = radius * 2f;

            GraphicsPath gp = new GraphicsPath();
            gp.AddArc(rectangle.X, rectangle.Y, size, size, 180, 90);
            gp.AddArc(rectangle.X + rectangle.Width - size, rectangle.Y, size, size, 270, 90);
            gp.AddLine(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height, rectangle.X, rectangle.Y + rectangle.Height);
            gp.CloseFigure();
            g.FillPath(brush, gp);
            gp.Dispose();
        } 
        #endregion

        #region DrawShadow
        internal static void DrawShadow(Graphics g, Rectangle rect)
        {
            Color cBorder = Color.FromArgb(141, 178, 227);
            g.DrawRectangle(new Pen(cBorder), new Rectangle(rect.X - 1, rect.Y - 1, rect.Width + 1, rect.Height + 1));
            SolidBrush b1 = new SolidBrush(Color.FromArgb(10, Color.Black));
            //Button
            Rectangle f = new Rectangle(rect.X - 2, rect.Y + rect.Height, rect.Width + 3, 3);
            g.FillRectangle(b1, f);
            f = new Rectangle(rect.X - 2, rect.Y + rect.Height, rect.Width + 3, 2);
            g.FillRectangle(b1, f);
            //Right
            f = new Rectangle(rect.X + rect.Width, rect.Y, 3, rect.Height);
            g.FillRectangle(b1, f);
            f = new Rectangle(rect.X + rect.Width, rect.Y, 2, rect.Height);
            g.FillRectangle(b1, f);
            //Top
            f = new Rectangle(rect.X - 2, rect.Y - 3, rect.Width + 3, 3);
            g.FillRectangle(b1, f);
            f = new Rectangle(rect.X - 2, rect.Y - 2, rect.Width + 3, 2);
            g.FillRectangle(b1, f);
            //Left
            f = new Rectangle(rect.X - 3, rect.Y, 3, rect.Height);
            g.FillRectangle(b1, f);
            f = new Rectangle(rect.X - 2, rect.Y, 2, rect.Height);
            g.FillRectangle(b1, f);
        } 
        #endregion

        #region DrawShadowTop
        internal static void DrawShadowTop(Graphics g, Rectangle rect)
        {
            g.FillRectangle(new SolidBrush(Color.FromArgb(8, Color.Black)), rect);
            rect.Inflate(rect.Width, 3);
            g.FillRectangle(new SolidBrush(Color.FromArgb(7, Color.Black)), rect);
            rect.Inflate(rect.Width, 2);
            g.FillRectangle(new SolidBrush(Color.FromArgb(6, Color.Black)), rect);
            rect.Inflate(rect.Width, 1);
            g.FillRectangle(new SolidBrush(Color.FromArgb(5, Color.Black)), rect);
        } 
        #endregion

        #region GetBrush
        internal static LinearGradientBrush GetBrush(Color[] col, float[] pos, Rectangle rect)
        {
            ColorBlend blend = new ColorBlend();
            blend.Colors = col;
            blend.Positions = pos;
            LinearGradientBrush brush = new LinearGradientBrush(rect, Color.Transparent, Color.Transparent, LinearGradientMode.Vertical);
            brush.InterpolationColors = blend;

            return brush;
        } 
        #endregion

        #region RenderSelection
        internal static void RenderSelection(Graphics g, Rectangle rect, float radius, bool pressed)
        {
            if (pressed)
            {
                Color[] col = new Color[] { Color.FromArgb(254, 216, 170), Color.FromArgb(251, 181, 101), Color.FromArgb(250, 157, 52), Color.FromArgb(253, 238, 170) };
                float[] pos = new float[] { 0.0f, 0.4f, 0.4f, 1.0f };

                LinearGradientBrush brush = GetBrush(col, pos, rect);
                FillRoundRectangle(g, brush, rect, 2f);
                DrawRoundRectangle(g, new Pen(Color.FromArgb(171, 161, 140)), rect, radius);
                rect.Offset(1, 1);
                rect.Width -= 2;
                rect.Height -= 2;
                DrawRoundRectangle(g, new Pen(new LinearGradientBrush(rect, Color.FromArgb(223, 183, 136), Color.Transparent, LinearGradientMode.ForwardDiagonal)), rect, radius);
            }
            else
            {
                Color[] col = new Color[] { Color.FromArgb(255, 254, 227), Color.FromArgb(255, 231, 151), Color.FromArgb(255, 215, 80), Color.FromArgb(255, 231, 150) };
                float[] pos = new float[] { 0.0f, 0.4f, 0.4f, 1.0f };

                LinearGradientBrush brush = GetBrush(col, pos, rect);
                FillRoundRectangle(g, brush, rect, 2f);
                DrawRoundRectangle(g, new Pen(Color.FromArgb(210, 192, 141)), rect, radius);
                rect.Offset(1, 1);
                rect.Width -= 2;
                rect.Height -= 2;
                DrawRoundRectangle(g, new Pen(new LinearGradientBrush(rect, Color.FromArgb(255, 255, 247), Color.Transparent, LinearGradientMode.ForwardDiagonal)), rect, 2f);
            }
        } 
        #endregion

        #region RenderTopSelection
        public static void RenderTopSelection(Graphics g, Rectangle rect, float radius, bool pressed)
        {
            if (pressed)
            {
                Color[] col = new Color[] { Color.FromArgb(254, 216, 170), Color.FromArgb(251, 181, 101), Color.FromArgb(250, 157, 52), Color.FromArgb(253, 238, 170) };
                float[] pos = new float[] { 0.0f, 0.4f, 0.4f, 1.0f };

                LinearGradientBrush brush = GetBrush(col, pos, rect);
                FillTopRoundRectangle(g, brush, rect, 2f);
                DrawTopRoundRectangle(g, new Pen(Color.FromArgb(171, 161, 140)), rect, radius);
                rect.Offset(1, 1);
                rect.Width -= 2;
                rect.Height -= 2;
                DrawTopRoundRectangle(g, new Pen(new LinearGradientBrush(rect, Color.FromArgb(223, 183, 136), Color.Transparent, LinearGradientMode.ForwardDiagonal)), rect, radius);
            }
            else
            {
                Color[] col = new Color[] { Color.FromArgb(255, 254, 227), Color.FromArgb(255, 231, 151), Color.FromArgb(255, 215, 80), Color.FromArgb(255, 231, 150) };
                float[] pos = new float[] { 0.0f, 0.4f, 0.4f, 1.0f };
                LinearGradientBrush brush = GetBrush(col, pos, rect);
                FillTopRoundRectangle(g, brush, rect, 2f);

                DrawTopRoundRectangle(g, new Pen(Color.FromArgb(210, 192, 141)), rect, radius);
                rect.Offset(1, 1);
                rect.Width -= 2;
                rect.Height -= 2;
                DrawTopRoundRectangle(g, new Pen(new LinearGradientBrush(rect, Color.FromArgb(255, 255, 247), Color.Transparent, LinearGradientMode.ForwardDiagonal)), rect, 2f);
            }
        } 
        #endregion

        #region CreateThumbnail
        static public Image CreateThumbnail(Image originalImage, int imageHeight)
        {
            // create thumbnail
            float ratio = (float)originalImage.Width / originalImage.Height;
            int imageWidth = (int)(imageHeight * ratio);

            // set the thumbnail image
            Image thumbnailImage = originalImage.GetThumbnailImage(imageWidth, imageHeight,
                new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero);

            return thumbnailImage;
        } 
        #endregion

        #region ThumbnailCallback
        static private bool ThumbnailCallback()
        {
            return true;
        } 
        #endregion

        #region ScaleToFit
        static public Rectangle ScaleToFit(Image image, Rectangle targetArea, bool strechToFit)
        {
            Rectangle result;
            if (image.Width < targetArea.Width && image.Height < targetArea.Height)
            {
                if (strechToFit)
                {
                    float widthRatio = (float)targetArea.Width / (float)image.Width;
                    float heightRatio = (float)targetArea.Height / (float)image.Height;
                    float minRatio = Math.Min(widthRatio, heightRatio);
                    result = new Rectangle(targetArea.X, targetArea.Y, (int)(image.Width * minRatio), (int)(image.Height * minRatio));
                    if (result.Width < targetArea.Width)
                    {
                        result.X += (targetArea.Width - result.Width) / 2;
                    }
                    if (result.Height < targetArea.Height)
                    {
                        result.Y += (targetArea.Height - result.Height) / 2;
                    }
                }
                else
                {
                    // the image size is less than the targetArea size
                    result = new Rectangle(targetArea.Location, image.Size);
                    result.X += (targetArea.Width - result.Width) / 2;
                    result.Y += (targetArea.Height - result.Height) / 2;
                }
            }
            else	// the width or height of the image is greater than the targetArea
            {
                result = new Rectangle(targetArea.Location, targetArea.Size);
                // determine best fit: width or height
                if (image.Width * result.Height > image.Height * result.Width)
                {
                    // final width should match target, determine and center height
                    result.Height = result.Width * image.Height / image.Width;
                    result.Y += (targetArea.Height - result.Height) / 2;
                }
                else
                {
                    // final height should match target, determine and center width
                    result.Width = result.Height * image.Width / image.Height;
                    result.X += (targetArea.Width - result.Width) / 2;
                }
            }

            return result;
        } 
        #endregion

        #region GetIconFromImage
        //internal static Icon GetIcon(int index)
        //{
        //    Bitmap img = Portal.Properties.Resources.LogoAni;
        //    Bitmap imgIcon = new Bitmap(24, 24);
        //    Graphics g = Graphics.FromImage(imgIcon);
        //    Rectangle rectImg = new Rectangle(24 * index, 0, 24, 24);
        //    g.DrawImage(img, new Rectangle(0, 0, 24, 24), rectImg, GraphicsUnit.Pixel);
        //    Icon icn = Icon.FromHandle(imgIcon.GetHicon());
        //    g.Dispose();
        //    return icn;
        //}

        internal static List<Icon> GetIconList()
        {
            List<Icon> iconList = new List<Icon>();
            Bitmap img = Properties.Resources.Logo24;
            Bitmap imgIcon = new Bitmap(24, 24);
            Graphics g = Graphics.FromImage(imgIcon);
            for (int i = 0; i <= 23; i++)
            {
                Rectangle rectImg = new Rectangle(24 * i, 0, 24, 24);
                g.DrawImage(img, new Rectangle(0, 0, 24, 24), rectImg, GraphicsUnit.Pixel);
                Icon icn = Icon.FromHandle(imgIcon.GetHicon());
                iconList.Add(icn);
                g.Clear(Color.Transparent);
            }
            g.Dispose();
            return iconList;
        }
        #endregion

    }
}
